package decision

import (
	"embed"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"
	"sync"
)

// PromptTemplate 系统提示词模板
type PromptTemplate struct {
	Name    string // 模板名称（文件名，不含扩展名）
	Content string // 模板内容
}

// PromptManager 提示词管理器
type PromptManager struct {
	templates map[string]*PromptTemplate
	mu        sync.RWMutex
}

var (
	// globalPromptManager 全局提示词管理器
	globalPromptManager *PromptManager
	// promptsDir 提示词文件夹路径（运行时解析）
	promptsDir = resolvePromptsDir()
	// embeddedPromptsFS 内置默认提示词（编译期嵌入）
	//go:embed prompts/*.txt
	embeddedPromptsFS embed.FS
)

// 解析提示词目录，优先级：ENV -> 工作目录 ./prompts -> 可执行文件目录/prompts
func resolvePromptsDir() string {
	// 1) 环境变量覆盖
	if envDir := strings.TrimSpace(os.Getenv("PROMPTS_DIR")); envDir != "" {
		return envDir
	}
	// 2) 当前工作目录下的 prompts
	cwdDir := "prompts"
	if st, err := os.Stat(cwdDir); err == nil && st.IsDir() {
		return cwdDir
	}
	// 3) 可执行文件所在目录下的 prompts
	exePath, err := os.Executable()
	if err == nil {
		exeDir := filepath.Dir(exePath)
		exePrompts := filepath.Join(exeDir, "prompts")
		if st, err := os.Stat(exePrompts); err == nil && st.IsDir() {
			return exePrompts
		}
	}
	// 4) 兜底返回默认（仍会在加载时报错，便于日志提示）
	return "prompts"
}

// init 包初始化时加载所有提示词模板
func init() {
	globalPromptManager = NewPromptManager()
	if err := globalPromptManager.LoadTemplates(promptsDir); err != nil {
		log.Printf("⚠️  加载提示词模板失败: %v", err)
	} else {
		log.Printf("✓ 已加载 %d 个系统提示词模板", len(globalPromptManager.templates))
	}
}

// NewPromptManager 创建提示词管理器
func NewPromptManager() *PromptManager {
	return &PromptManager{
		templates: make(map[string]*PromptTemplate),
	}
}

// 加载内置默认模板（编译期嵌入）
func (pm *PromptManager) loadEmbeddedDefaults() {
	entries, err := embeddedPromptsFS.ReadDir("prompts")
	if err != nil {
		log.Printf("⚠️  读取内置提示词目录失败: %v", err)
		return
	}
	for _, e := range entries {
		if e.IsDir() { // 忽略子目录
			continue
		}
		name := e.Name()
		if !strings.HasSuffix(strings.ToLower(name), ".txt") {
			continue
		}
		content, err := embeddedPromptsFS.ReadFile(filepath.ToSlash(filepath.Join("prompts", name)))
		if err != nil {
			log.Printf("⚠️  读取内置提示词失败 %s: %v", name, err)
			continue
		}
		templateName := strings.TrimSuffix(name, filepath.Ext(name))
		pm.templates[templateName] = &PromptTemplate{
			Name:    templateName,
			Content: string(content),
		}
		log.Printf("  📄 内置提示词模板: %s (%s)", templateName, name)
	}
}

// LoadTemplates 从指定目录加载所有提示词模板（内置默认 + 外部覆盖）
func (pm *PromptManager) LoadTemplates(dir string) error {
	pm.mu.Lock()
	defer pm.mu.Unlock()

	// 先加载内置默认模板
	pm.templates = make(map[string]*PromptTemplate)
	pm.loadEmbeddedDefaults()

	// 再尝试加载外部目录（如果不存在，不作为错误）
	if st, err := os.Stat(dir); err != nil || !st.IsDir() {
		log.Printf("⚠️  外部提示词目录不可用，使用内置默认: %s", dir)
		return nil
	}

	files, err := filepath.Glob(filepath.Join(dir, "*.txt"))
	if err != nil {
		return fmt.Errorf("扫描提示词目录失败: %w", err)
	}
	if len(files) == 0 {
		log.Printf("⚠️  外部目录 %s 中没有找到 .txt 文件，继续使用内置默认", dir)
		return nil
	}

	// 外部模板覆盖内置同名模板
	for _, file := range files {
		content, err := os.ReadFile(file)
		if err != nil {
			log.Printf("⚠️  读取外部提示词文件失败 %s: %v", file, err)
			continue
		}
		fileName := filepath.Base(file)
		templateName := strings.TrimSuffix(fileName, filepath.Ext(fileName))
		pm.templates[templateName] = &PromptTemplate{
			Name:    templateName,
			Content: string(content),
		}
		log.Printf("  📄 外部提示词覆盖: %s (%s)", templateName, fileName)
	}

	return nil
}

// GetTemplate 获取指定名称的提示词模板
func (pm *PromptManager) GetTemplate(name string) (*PromptTemplate, error) {
	pm.mu.RLock()
	defer pm.mu.RUnlock()

	template, exists := pm.templates[name]
	if !exists {
		return nil, fmt.Errorf("提示词模板不存在: %s", name)
	}
	return template, nil
}

// GetAllTemplateNames 获取所有模板名称列表
func (pm *PromptManager) GetAllTemplateNames() []string {
	pm.mu.RLock()
	defer pm.mu.RUnlock()
	names := make([]string, 0, len(pm.templates))
	for name := range pm.templates {
		names = append(names, name)
	}
	return names
}

// GetAllTemplates 获取所有模板
func (pm *PromptManager) GetAllTemplates() []*PromptTemplate {
	pm.mu.RLock()
	defer pm.mu.RUnlock()
	templates := make([]*PromptTemplate, 0, len(pm.templates))
	for _, template := range pm.templates {
		templates = append(templates, template)
	}
	return templates
}

// ReloadTemplates 重新加载所有模板（重新解析目录并合并内置）
func (pm *PromptManager) ReloadTemplates(dir string) error {
	pm.mu.Lock()
	pm.templates = make(map[string]*PromptTemplate)
	pm.mu.Unlock()
	pm.loadEmbeddedDefaults()
	return pm.LoadTemplates(dir)
}

// === 全局函数（供外部调用）===

// GetPromptTemplate 获取指定名称的提示词模板（全局函数）
func GetPromptTemplate(name string) (*PromptTemplate, error) {
	return globalPromptManager.GetTemplate(name)
}

// GetAllPromptTemplateNames 获取所有模板名称（全局函数）
func GetAllPromptTemplateNames() []string {
	return globalPromptManager.GetAllTemplateNames()
}

// GetAllPromptTemplates 获取所有模板（全局函数）
func GetAllPromptTemplates() []*PromptTemplate {
	return globalPromptManager.GetAllTemplates()
}

// ReloadPromptTemplates 重新加载所有模板（全局函数）
func ReloadPromptTemplates() error {
	// 保持与初始化时解析的一致性
	promptsDir = resolvePromptsDir()
	globalPromptManager.mu.Lock()
	globalPromptManager.templates = make(map[string]*PromptTemplate)
	globalPromptManager.mu.Unlock()
	globalPromptManager.loadEmbeddedDefaults()
	return globalPromptManager.LoadTemplates(promptsDir)
}
